home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Tools / Utility / DisplayNameRegistry 950412 / Src / TwistDownList.h < prev   
Encoding:
C/C++ Source or Header  |  1997-02-27  |  18.6 KB  |  496 lines  |  [TEXT/MPCC]

  1. /*                                    TwistDownList.h                                */
  2. /*
  3.  * List In A List Sample
  4.  * TwistDownList.h
  5.  * Copyright © 1993-94 Apple Computer Inc. All rights reserved.
  6.  * Edit History
  7.  * 94.01.03 MM    Original release for the develop article.
  8.  * 94.10.16 MM    Use pascal calling conventions (reader suggestion). Reserved flag
  9.  *                bits for application programs; added a sort function; changed the
  10.  *                user-specified drawing function so that the TwistDownRecord is
  11.  *                passed (as a pointer to a locked handle) so that the drawing
  12.  *                function can access the flag bits. Added horizontal scrollbar
  13.  *                support. Added "sibling-set" functions to simplify normal list
  14.  *                operation. Updated to Universal Headers (ETO 15).
  15.  * 94.11.26 MM    Updated for headers "Universal Interfaces 2.0a3c1" -- these
  16.  *                are incompatible with ETO 15.
  17.  *
  18.  * Note that "list" is ambiguous, referring either to a List Manager list or to
  19.  * a "Lisp-like" list. In the following documentation, "cell" will always refer
  20.  * to a List Manager list cell, while "element" will always refer to a Lisp
  21.  * cell. Note that elements are not always displayed by the List Manager.
  22.  */
  23. #ifndef _TwistDownList_
  24. #define _TwistDownList_
  25.  
  26. #ifndef REZ
  27. #include "ConditionalMacros.h"
  28. #include "Types.h"
  29. #include "MixedMode.h"
  30. #include "OSUtils.h"
  31. #include "Files.h"
  32. #include "QuickdrawText.h"
  33. #include "QuickDraw.h"
  34. #include "Events.h"
  35. #include "Errors.h"
  36. #include "Memory.h"
  37. #include "Menus.h"
  38. #include "Controls.h"
  39. #include "Windows.h"
  40. #include "TextEdit.h"
  41. #include "Dialogs.h"
  42. #include "MachineExceptions.h"
  43. #if 1 /* This is for PCI development only */
  44. #include "Kernel.h"
  45. #include "NameRegistry.h"
  46. #include "CodeFragments.h"
  47. #endif
  48. #include "Devices.h"
  49. #include "Fonts.h"
  50. #include "Resources.h"
  51. #include "LowMem.h"
  52. #include "Lists.h"
  53. #include "IntlResources.h"
  54. #include "Script.h"
  55. #include "TextUtils.h"
  56. #include "SegLoad.h"
  57. #include "FixMath.h"
  58. #include "ToolUtils.h"
  59. #include "Printing.h"
  60.  
  61. #ifndef TRUE
  62. #define TRUE                1
  63. #define FALSE                0
  64. #endif
  65. #ifndef NULL
  66. #define NULL                0
  67. #endif
  68. /*
  69.  * This is the resource ID of the callback stub that must be defined in the
  70.  * application's resource fork. See the example in ListInAList.r.
  71.  */
  72. #define LDEF_Stub            1024
  73. /*
  74.  * TwistDownClickState is the value returned by DoTwistDownClick.
  75.  */
  76. typedef enum {
  77.     kTwistDownNotInList = 0,            /* The click was not in this list        */
  78.     kTwistDownNoClick,                    /* User changed mind                    */
  79.     kTwistDownButtonClick,                /* Clicked on twist-down button            */
  80.     kTwistDownClick,                    /* Single-click on list datum            */
  81.     kTwistDownDoubleClick                /* Double-click on list datum            */
  82. } TwistDownClickState;
  83.  
  84. /*
  85.  * This is the information needed to manage the twist-down display list. It is,
  86.  * essentially, a classical Lisp list with recursively-defined sublists. Each
  87.  * element contains enough information to display one component. This list is
  88.  * stored in a handle stored in the list's private data handle. The ListManager
  89.  * list cells contain TwistDownHdl pointers to the visible elements.
  90.  * A value of NULL in nextElement indicates the end of a list or sublist.
  91.  * A value of NULL in subElement means that there are no sub-elements (this
  92.  * is a leaf). Note that the Macintosh memory manager handles garbage collection.
  93.  *
  94.  * The flag bits have the following meanings:
  95.  *    kHasTwistDown        This list element is a sub-list (it may be empty).
  96.  *                        Draw the twist-down button (even if subElement is NULL).
  97.  *    kShowSubList        This list element is has a sub-list and the user wants
  98.  *                        to see the contents of the sub-list, too.
  99.  *    kOldShowSubList        This would be used to save the state of the kShowSubList
  100.  *                        flag if it needs to be changed temporarily (to show
  101.  *                        the entire hierarchy, for example).
  102.  * The following flags are only needed by the mouse-click handler.
  103.  *    kDrawButtonFilled    This is used by the mouse-click handler to signal
  104.  *                        "mouse-down in button." The LDEF fills the button area.
  105.  *    kOnlyRedrawButton    This is used by the mouse-click handler to signal the
  106.  *                        LDEF to draw only the button, but not the list content.
  107.  *    kDrawIntermediate    The user is expanding/collapsing the folder. Draw
  108.  *                        the animation triangle.
  109.  *    kSelectedElement    This element was selected in the display list. This is
  110.  *                        a temporary value needed when the list is expanded or
  111.  *                        contracted.
  112.  *    kEraseButtonArea    If we are only hiliting the button (while the user has
  113.  *                        pressed the mouse in the button area), we don't need to
  114.  *                        erase the button before redrawing it. When the user clicks
  115.  *                        -- releases the mouse in the button -- the button shape
  116.  *                        will change, so the old shape must be erased. This is
  117.  *                        controlled by this flag.
  118.  * kUserFlagMask        These flags may be used by the calling program.
  119.  */
  120. #define kHasTwistDown        0x0001                /* This element has a sub-list    */
  121. #define    kShowSublist        0x0002                /* Display the sub-list content    */
  122. #define    kOldShowSublist        0x0004                /* Save kShowSublist state        */
  123. #define    kSelectedElement    0x0008                /* Copy "selected" from List    */
  124. #define    kDrawButtonFilled    0x0010                /* Signal "mouseDown" in button    */
  125. #define    kOnlyRedrawButton    0x0020                /* Signal "tracking mouse"        */
  126. #define kDrawIntermediate    0x0040                /* Draw the animation polygon    */
  127. #define    kEraseButtonArea    0x0080                /* Need complete button redraw    */
  128. #define kUserFlagMask        0xFF00                /* Reserved for caller's use    */
  129. #define kFirstUserFlag        0x0100                /* User flags start here        */
  130. #define kUserFlagShift        8                    /* Shift to first user flag bit    */
  131.  
  132. struct TwistDownRecord {
  133.     struct TwistDownRecord    **nextElement;        /* CDR - next on this "level"    */
  134.     struct TwistDownRecord    **subElement;        /* CAR - first in a sublist        */
  135.     short                indentLevel;            /* Indentation depth            */
  136.     unsigned short        flag;                    /* TwistDownFlags                */
  137.     unsigned short        dataLength;                /* Length of actual datum        */
  138.     unsigned char        data[1];                /* Datum to display                */
  139. };
  140. typedef struct TwistDownRecord    TwistDownRecord, *TwistDownPtr, **TwistDownHdl;
  141.  
  142. /*
  143.  * TwistDownSiblingSet simplifies creation of a linked list of TwistDown elements.
  144.  * Usage:
  145.  *        NewTwistDownSiblingSet(&mySiblingSet);
  146.  *        status = MakeTwistDownSibling(&mySiblingSet, ...);
  147.  *        currentElement = mySiblingSet.thisElement;
  148.  *        (**currentElement).subElement = EnumerateChildOfCurrentElement(...);
  149.  *        return (mySiblingSet.firstElement);
  150.  */
  151. struct TwistDownSiblingSet {
  152.     TwistDownHdl        thisElement;            /* This was just created        */
  153.     TwistDownHdl        firstElement;            /* First in this sequence        */
  154.     TwistDownHdl        previousElement;        /* Previous element linkage        */
  155. };
  156. typedef struct TwistDownSiblingSet TwistDownSiblingSet, *TwistDownSiblingSetPtr;
  157.  
  158. /*
  159.  * This is the function that is called to draw the user-specified list cell
  160.  * contents. The port and font have been properly initialized and the viewRect
  161.  * takes indentation into consideration. If this parameter is specified as NULL,
  162.  * DrawText will be used. Note that the application can use the list's refCon to
  163.  * pass other data to the drawing procedure.
  164.  *
  165.  * This function will be called to draw list cells on the display and, if the
  166.  * default print page procedure is provided, to print list element information.
  167.  *
  168.  * Note: this is an incompatible change from the original release of the TwistDown
  169.  * library that makes it possible for the drawing procedure to access the user-
  170.  * controlled flag bits and (though it should not be necessary) the indent level.
  171.  */
  172. typedef pascal void            (*TwistDownDrawProc)(
  173.         ListHandle                twistDownListHdl,    /* The list itself            */
  174.         TwistDownPtr            twistDownPtr,        /* Locked data handle        */
  175.         const Rect                *viewRect            /* Draw in this area        */
  176.     );
  177.  
  178. /*
  179.  * Create a twist-down list. Before calling, you must set the port to the current
  180.  * window and specify the font and font size that is to be used to draw the list.
  181.  * NewTwistDownList creates an empty one-column list with a vertical scroll bar
  182.  * and no grow box. Only one item may be selected at a time; but this could
  183.  * be changed by the application without difficulty.
  184.  *
  185.  * Note: unlike LNew, you should specify a correct viewRect: the scroll bars and
  186.  * frame will be created inside the view rect.
  187.  *
  188.  * The TwistDownDrawProc will be called to draw a selection. If specified as
  189.  * NULL, DrawText will be called.
  190.  *
  191.  * The tabIndent parameter should be set to the amount to indent successive levels
  192.  * (zero means no indentation). Setting it to the widMax value from the current
  193.  * font seems reasonable.
  194.  *
  195.  * canHiliteSelection should be TRUE for normal selection (the selection is
  196.  * hilited). It should be FALSE if you want to supress selection. Because
  197.  * hirearchical lists often "select" by revealing a sub-topic, this may be
  198.  * more reasonable in many cases.
  199.  *
  200.  * isLeftJustify should be set TRUE for systems using the Roman alphabet. It would
  201.  * be set FALSE for right-to-left languages such as Arabic and Hebrew. It is used
  202.  * to configure the direction of the buttons and the location of text within
  203.  * the displayed list cell.
  204.  */
  205. pascal ListHandle            NewTwistDownList(
  206.         const Rect                *viewRect,
  207.         TwistDownDrawProc        drawProc,
  208.         unsigned short            tabIndent,
  209.         Boolean                    canHiliteSelection,
  210.         Boolean                    isLeftJustify,
  211.         Boolean                    hasGrowBox
  212.     );
  213. /*
  214.  * Dispose of a Twist Down List and its private storage. The application program
  215.  * must itself dispose of the list data. theList may be NULL.
  216.  */
  217. pascal void                    DisposeTwistDownList(
  218.         ListHandle                theList
  219.     );
  220.  
  221. /*
  222.  * Move the list within the window.
  223.  */
  224. pascal void                    MoveTwistDownList(
  225.         ListHandle                theList,
  226.         short                    leftEdge,
  227.         short                    topEdge
  228.     );
  229. /*
  230.  * Resize the list. The width and height parameters do not include the horizontal
  231.  * and vertical scrollbars.
  232.  */
  233. pascal void                    SizeTwistDownList(
  234.         ListHandle                theList,
  235.         short                    newWidth,
  236.         short                    newHeight
  237.     );
  238. /*
  239.  * CreateTwistDownButtons is called, internally, when the list is created.
  240.  * if the application program changes the list cell height (by calling LSize),
  241.  * or changes the direction of text it must re-call CreateTwistDownButtons
  242.  * to re-create the twist-down buttons.
  243.  */
  244. pascal void                    CreateTwistDownButtons(
  245.         ListHandle                theList
  246.     );
  247. /*
  248.  * DoTwistDownClick handles all processing after a click in the list window.
  249.  * It returns an indication of the user action:
  250.  *    kTwistDownNotInList
  251.  *        The click was not in this list. Your application may ignore this click or
  252.  *        take other appropriate action.
  253.  *    kTwistDownNoClick
  254.  *        The user released the mouse outside of the list area: this click should be
  255.  *        ignored.
  256.  *    kTwistDownButtonClick
  257.  *        The user clicked on the twist-down button. Expand or contract the list as
  258.  *        appropriate.
  259.  *    kTwistDownClick
  260.  *        The user clicked (once) on a list datum. The application should treat this
  261.  *        as an item selection (or, it may be a click in the scroll bar). This is
  262.  *        the result of a FALSE return from LClick.
  263.  *    kTwistDownDoubleClick
  264.  *        The user double-clicked on a list datum. The application should open this
  265.  *        item or take other appropriate action. This is the result of a TRUE
  266.  *        return from LClick.
  267.  *
  268.  * If DoTwistDownClick returns kTwistDownButtonClick, kTwistDownClick, or
  269.  * kTwistDownDoubleClick, selectedListCell will be set to the cell that the user
  270.  * clicked on.
  271.  */
  272. pascal TwistDownClickState    DoTwistDownClick(
  273.         ListHandle                theList,
  274.         const EventRecord        *eventRecordPtr,
  275.         Cell                    *selectedListCell
  276.     );
  277. /*
  278.  * ExpandOrCollapseTwistdownSubList is called when the user clicks on the
  279.  * twist-down button. index and selectedListCell are the values returned by
  280.  * DoTwistDownClick.
  281.  */
  282. pascal void                    ExpandOrCollapseTwistDownList(
  283.         ListHandle                theList,
  284.         Cell                    selectedListCell
  285.     );
  286. /*
  287.  * SetTwistDownListFont changes the font and font size. It then calls
  288.  * CreateTwistDownButtons to change the twist down button dimensions.
  289.  * SetTwistDownListFont will cause the list to be redrawn, but it does not
  290.  * examine or modify the TwistDown list elements.
  291.  */
  292. pascal void                    SetTwistDownListFont(
  293.         ListHandle                theList,
  294.         short                    fontNumber,
  295.         short                    fontSize
  296.     );
  297. /*
  298.  * Explicitly update a list without waiting for an update event. This would
  299.  * normally only be called after an Alert or Modal Dialog terminates.
  300.  */
  301. pascal void                    UpdateTwistDownList(
  302.         ListHandle                theList
  303.     );
  304.  
  305. /*
  306.  * CreateVisibleList is called when the list is created. It stores the list
  307.  * head into cell [0, 0] and calls BuildVisibleList to instantiate the display.
  308.  */
  309. pascal void                    CreateVisibleList(
  310.         ListHandle                theList,
  311.         TwistDownHdl            twistDownHdl
  312.     );
  313. /*
  314.  * BuildVisibleList is called when the list is created, or when the user clicks on
  315.  * a twist-down button. selectedRow is the first row that needs to be redrawn. The
  316.  * head of the entire list has been stored into cell [0, 0].
  317.  */
  318. pascal void                    BuildVisibleList(
  319.         ListHandle                theList,
  320.         short                    selectedRow
  321.     );
  322. /*
  323.  * GetTwistDownElementHandle returns the TwistDownHdl that is stored in a List
  324.  * cell. It will return NULL if the cell is out of bounds.
  325.  */
  326. pascal TwistDownHdl            GetTwistDownElementHandle(
  327.         ListHandle                theList,
  328.         Cell                    theCell
  329.     );
  330. /*
  331.  * NewTwistDownSiblingSet initializes the variables that will be used to manage
  332.  * a linked list of TwistDown list elements. Together with MakeSibling, it simplifies
  333.  * management of the list.
  334.  */
  335. pascal void                    NewTwistDownSiblingSet(
  336.         TwistDownSiblingSetPtr    twistDownSiblingSetPtr
  337.     );
  338. /*
  339.  * MakeTwistDownSibling adds a new element (by calling MakeTwistDownElement) to
  340.  * the end of the current linked list. It handles the bookkeeping needed for
  341.  * the first element.
  342.  */
  343. pascal OSErr                MakeTwistDownSibling(
  344.         TwistDownSiblingSetPtr    twistDownSiblingSetPtr,
  345.         short                    indentLevel,
  346.         unsigned short            dataLength,
  347.         const Ptr                dataPtr
  348.     );
  349. /*
  350.  * MakeTwistDownElement adds an element to a linked list. It is designed to create
  351.  * elements in a hierarchical linked-list where each element may be followed by a
  352.  * successor (on the same "level") and/or by a child list (on a lower "level").
  353.  * The parameters are as follows:
  354.  *    previousElement
  355.  *        This has a handle to the predecessor to this element. PreviousElement
  356.  *        should be NULL if this is the first element.
  357.  *    indentLevel
  358.  *        This is the indentation-level of this list element. It is only used to tab
  359.  *        the list elements on the visual display. If you never want tabbing, set
  360.  *        tabIndent to zero when the list was created. Indents start at zero.
  361.  *    dataLength
  362.  *        This is the length of the list element datum.
  363.  *    dataPtr
  364.  *        This is a pointer to the first byte of the list element datum. If NULL,
  365.  *        a data block of the requisite size will be created, but the caller is
  366.  *        responsible for filling it in.
  367.  *    result
  368.  *        If MakeElement succeeds, result will will contain a handle to the
  369.  *        list element it created. This is needed to create a successor
  370.  *        element.
  371.  */
  372. pascal OSErr                MakeTwistDownElement(
  373.         TwistDownHdl            previousElement,
  374.         short                    indentLevel,
  375.         unsigned short            dataLength,
  376.         const Ptr                dataPtr,
  377.         TwistDownHdl            *result
  378.     );
  379.  
  380. /*
  381.  * Append the second list to the first. Return the first element.
  382.  */
  383. pascal TwistDownHdl            AppendTwistDownList(
  384.         TwistDownHdl            dstTwistDownHandle,
  385.         TwistDownHdl            srcTwistDownHdl
  386.     );
  387.  
  388. /*
  389.  * This recursive function disposes of the argument list that has the argument
  390.  * at its head, and of all sublists linked to this list. If userProc is non-NULL,
  391.  * it will be called when disposing each handle. This allows the caller to
  392.  * store handle or pointer data within a list element.
  393.  */
  394. typedef pascal void            (*DisposeTwistDownCallback)(
  395.         TwistDownHdl            twistDownHdl,
  396.         void                    *userData
  397.     );
  398.         
  399. pascal void                    DisposeTwistDownHdl(
  400.         TwistDownHdl            twistDownHdl,
  401.         DisposeTwistDownCallback userProc,
  402.         void                    *userData
  403.     );
  404.  
  405. /*
  406.  * Count the number of elements in the list (whether visible or not).
  407.  */
  408. pascal unsigned long        CountListElements(
  409.         TwistDownHdl            twistDownHdl
  410.     );
  411.  
  412. /*
  413.  * Sort a TwistDown list. This sorts the current list, but does not examine any
  414.  * sublists. The caller must provide a comparison function.
  415.  *
  416.  * To sort a list, call SortTwistDownList(&theList, compareFunc, refCon). The
  417.  * sort is not recursive, and returns an error if the function cannot obtain
  418.  * enough scratch storage ((number of elements + 1) * sizeof (Handle))
  419.  */
  420. /*
  421.  * Compare two list elements, returning -1, 0, +1 depending on whether
  422.  * listElementA is less, equal to, or greater than listElementB.
  423.  */
  424. typedef pascal short        (*TwistDownSortCompareProc)(
  425.         void                    *refCon,
  426.         const TwistDownHdl        listElementA,
  427.         const TwistDownHdl        listElementB
  428.     );
  429. /*
  430.  * Sort a list according to the comparison function.
  431.  */
  432. pascal OSErr                SortTwistDownList(
  433.         TwistDownHdl            *twistDownHdlPtr,
  434.         TwistDownSortCompareProc twistDownSortCompareProc,
  435.         void                    *refCon
  436.     );
  437.  
  438. /*
  439.  * Print a TwistDown list. This is a print manager that calls user-provided
  440.  * functions to handle the actual printing process. (Default procedures are
  441.  * provided for text-only lists.) Parameters:
  442.  *        theList                    The ListHandle that contains this list.
  443.  *        printHandlePtr            This is the address of a PrintHandle. If the
  444.  *                                PrintHandle is NULL, a new handle will be
  445.  *                                allocated.
  446.  *        doStyleDialog            TRUE to always display the style dialog.
  447.  *        twistDownPrintSetupProc    This is called once to determine the number
  448.  *                                of pages in the printout. It should set
  449.  *                                (**hPrint).prJob.iLstPage to the total number
  450.  *                                of pages. See the default routine for details.
  451.  *                                If NULL, a default routine will be used that
  452.  *                                prints a simple heading (date, time, and page
  453.  *                                number), then uses the list font information
  454.  *                                to determine the number of pages.
  455.  *        twistDownPrintImageProc    This is called for each page to draw the data.
  456.  *                                If NULL, a default routine will be used that
  457.  *                                works with the setup function. This will use
  458.  *                                the cell display routine that was provided
  459.  *                                to the list creation function.
  460.  *        twistDownPrintExitProc    This is called when printing completes.
  461.  *        clientData                For the caller's use.
  462.  * The caller should call InitCursor (or whatever is appropriate) after
  463.  * PrintTwistDownList exits -- the cursor will be set to the watchCursor.
  464.  */
  465. typedef pascal OSErr (*TwistDownPrintSetupProc)(
  466.         ListHandle                theList,
  467.         THPrint                    printHandle,
  468.         void                    *clientData,
  469.         StringPtr                dateString
  470.     );
  471. typedef pascal OSErr (*TwistDownPrintImageProc)(
  472.         ListHandle                theList,
  473.         THPrint                    printHandle,
  474.         void                    *clientData,
  475.         StringPtr                dateString,
  476.         const Rect                *pageRect,
  477.         short                    pageNumber
  478.     );
  479. typedef pascal OSErr (*TwistDownPrintExitProc) (
  480.         ListHandle                theList,
  481.         void                    *clientData,
  482.         OSErr                    finalStatus
  483.     );
  484. pascal OSErr                PrintTwistDownList(
  485.         ListHandle                theList,
  486.         THPrint                    *printHandlePtr,
  487.         Boolean                    doStyleDialog,
  488.         TwistDownPrintSetupProc    twistDownPrintSetupProc,
  489.         TwistDownPrintImageProc    twistDownPrintImageProc,
  490.         TwistDownPrintExitProc    twistDownPrintExitProc,
  491.         void                    *clientData
  492.     );
  493.  
  494. #endif    /* REZ                */
  495. #endif    /* _TwistDownList_    */
  496.